package org.amphiprion.diceroller.screens;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.amphiprion.diceroller.PresetTagObject;
import org.amphiprion.diceroller.R;
import org.amphiprion.diceroller.TagObject;
import org.amphiprion.diceroller.dao.db.GamePresetDao;
import org.amphiprion.diceroller.entity.DiceDefinition;
import org.amphiprion.diceroller.entity.Game;
import org.amphiprion.diceroller.entity.GameDice;
import org.amphiprion.diceroller.entity.GamePreset;
import org.amphiprion.diceroller.screens.animation2d.Scale2DAnimation;
import org.amphiprion.diceroller.screens.animation2d.Translation2DAnimation;
import org.amphiprion.gameengine.GameScreen;
import org.amphiprion.gameengine.Group2D;
import org.amphiprion.gameengine.IObject2D;
import org.amphiprion.gameengine.Image2D;
import org.amphiprion.gameengine.Mesh;
import org.amphiprion.gameengine.ScreenProperty;
import org.amphiprion.gameengine.font.FontProvider;
import org.amphiprion.gameengine.font.Text2D;
import org.amphiprion.gameengine.font.Text2D.Alignment;
import org.amphiprion.gameengine.util.Vector4;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.text.Editable;
import android.view.MotionEvent;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.BounceInterpolator;
import android.widget.EditText;

public class ChoosePresetScreen extends GameScreen {
	private List<Mesh> selectedDices;
	private HashMap<String, DiceDefinition> diceDefinitions;

	private Image2D btOk;
	private Image2D btCancel;
	private CallBack callback;
	private Group2D presetElements;
	private String newId = null;
	private List<Image2D> presetButtons = new ArrayList<Image2D>();
	private List<Image2D> presetBgs = new ArrayList<Image2D>();

	private Context context;
	private Game game;
	private Image2D selectedPreset = null;

	public ChoosePresetScreen(Context context, String gameDirectory, Game game, HashMap<String, DiceDefinition> diceDefinitions, List<Mesh> selectedDices, CallBack callback) {
		this.context = context;
		this.game = game;
		this.selectedDices = selectedDices;
		this.diceDefinitions = diceDefinitions;
		this.callback = callback;

		Image2D bg = new Image2D(context, "D" + R.drawable.preset_bg);
		bg.x = 768 / 2;
		bg.y = 1280 / 2;

		backgroundObjects2d.add(bg);

		// btOk = new Image2D(context, "D" + R.drawable.ok);
		// btOk.x = 159;
		// btOk.y = 993;
		// objects2d.add(btOk);
		//
		btCancel = new Image2D(context, "D" + R.drawable.preset_close);
		btCancel.x = 768 / 2 + 323;
		btCancel.y = 1280 / 2 - 362;
		objects2d.add(btCancel);

		presetElements = new Group2D();
		presetElements.clipping = new Vector4(0, 320, 768, 625);
		objects2d.add(presetElements);

		int starty = 360;
		if (selectedDices != null && selectedDices.size() > 0) {
			Group2D presetGrp = new Group2D();
			presetGrp.setY(360);
			presetElements.addObject(presetGrp);

			Image2D newPreset = new Image2D(context, "D" + R.drawable.preset_item_sel_bg);
			newPreset.x = 768 / 2;
			newPreset.y = 360;
			presetGrp.addObject(newPreset);
			starty += 90;
			selectedPreset = newPreset;
			presetBgs.add(newPreset);

			int startX = 90;
			Text2D t = new Text2D(context, FontProvider.getFont("/resources/font/nightwarrior.fnt", "D" + R.drawable.nightwarrior));
			t.y = newPreset.y - 24;
			t.x = 768 / 2;
			presetGrp.addObject(t);
			t.setScale(0.35f);
			t.setText(context.getString(R.string.new_preset));
			t.alignment = Alignment.CENTER;

			String strDices = null;
			for (Mesh m : selectedDices) {
				TagObject tag = (TagObject) m.getTagObject();
				GameDice gd = tag.gameDice;
				Image2D d = new Image2D(context, "F" + gameDirectory + "/" + gd.getViewName());
				d.x = startX;
				d.y = newPreset.y + 20;
				startX += 40;
				presetGrp.addObject(d);
				d.setScale(0.3f);
				if (strDices != null) {
					strDices += "^" + gd.getId();
				} else {
					strDices = gd.getId();
				}
			}

			Image2D addBt = new Image2D(context, "D" + R.drawable.preset_add);
			addBt.x = newPreset.x + 290;
			addBt.y = newPreset.y;
			presetGrp.addObject(addBt);
			presetButtons.add(addBt);

			GamePreset gp = new GamePreset();
			newId = gp.getId();
			gp.setGamePath(gameDirectory);
			gp.setName("nameous");
			gp.setDices(strDices);
			PresetTagObject tag = new PresetTagObject();
			tag.gamePreset = gp;
			tag.presetGroup = presetGrp;
			tag.text2D = t;
			addBt.tagObject = tag;
			newPreset.tagObject = tag;
		}

		List<GamePreset> gamePresets = GamePresetDao.getInstance(context).getPresets(gameDirectory);
		for (int i = 0; i < gamePresets.size(); i++) {
			Group2D presetGrp = new Group2D();
			presetGrp.setY(starty + 90 * i);
			presetElements.addObject(presetGrp);

			GamePreset gp = gamePresets.get(i);

			Image2D p = new Image2D(context, "D" + R.drawable.preset_item_bg);
			p.x = 768 / 2;
			p.y = starty + 90 * i;
			presetGrp.addObject(p);
			presetBgs.add(p);

			Text2D t = new Text2D(context, FontProvider.getFont("/resources/font/nightwarrior.fnt", "D" + R.drawable.nightwarrior));
			t.y = p.y - 24;
			t.x = 768 / 2;
			presetGrp.addObject(t);
			t.setScale(0.35f);
			t.setText(gp.getName());
			t.alignment = Alignment.CENTER;

			String[] dices = gp.getDices().split("\\^");
			int startX = 90;
			for (String dice : dices) {
				GameDice gd = game.getGameDice(dice);
				Image2D d = new Image2D(context, "F" + gameDirectory + "/" + gd.getViewName());
				d.x = startX;
				d.y = p.y + 20;
				startX += 40;
				presetGrp.addObject(d);
				d.setScale(0.3f);

			}

			Image2D delBt = new Image2D(context, "D" + R.drawable.preset_delete);
			delBt.x = p.x + 290;
			delBt.y = p.y;
			presetGrp.addObject(delBt);
			presetButtons.add(delBt);

			PresetTagObject tag = new PresetTagObject();
			tag.gamePreset = gp;
			tag.presetGroup = presetGrp;
			tag.text2D = t;
			delBt.tagObject = tag;
			p.tagObject = tag;
		}
	}

	@Override
	public boolean isLayered() {
		return true;
	}

	@Override
	public void onDraw3D(float[] mMVPMatrix, float[] mViewMatrix, float[] mModelMatrix, float[] mProjectionMatrix, float[] mLightPosInEyeSpace) {
		super.onDraw3D(mMVPMatrix, mViewMatrix, mModelMatrix, mProjectionMatrix, mLightPosInEyeSpace);
		// btOk.rotationDegree = view.getScreenProperty().deviceAngle;
		// btCancel.rotationDegree = view.getScreenProperty().deviceAngle;

	}

	@Override
	public boolean backRequested() {
		view.removeScreen(1);
		return false;
	}

	private int lastTouchX;
	private int lastTouchY;
	private boolean touchMove = false;
	private boolean disableTouch;

	@Override
	public void onTouch(MotionEvent event) {
		if (disableTouch) {
			return;
		}
		ScreenProperty sp = view.getScreenProperty();

		int nx = (int) (event.getX() / sp.screenScaleX);
		int ny = (int) (event.getY() / sp.screenScaleY);
		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			lastTouchX = nx;
			lastTouchY = ny;
			touchMove = false;
		} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
			// if (ny >= 480 && ny <= 795) {
			int deltaX = nx - lastTouchX;
			int deltaY = ny - lastTouchX;
			if (!touchMove && Math.abs(deltaX) < 10 && Math.abs(deltaY) < 10) {
				return;
			}
			scrollItemsTo(presetElements.getY() + ny - lastTouchY);
			lastTouchY = ny;
			touchMove = true;
			// }
		} else if (event.getAction() == MotionEvent.ACTION_UP) {
			if (!touchMove) {
				if (btCancel.contains(nx, ny)) {
					selectButton(btCancel, new Runnable() {
						@Override
						public void run() {
							view.removeScreen(1);
						}
					});
				}

				List<IObject2D> buttons = new ArrayList<IObject2D>(presetButtons);
				for (IObject2D o : buttons) {
					final Image2D img = (Image2D) o;
					if (img.contains(nx, ny, 30)) {
						final GamePreset gp = ((PresetTagObject) img.tagObject).gamePreset;
						if (gp.getId().equals(newId)) {
							selectButton(img, new Runnable() {

								@Override
								public void run() {
									((Activity) context).runOnUiThread(new Runnable() {

										@Override
										public void run() {
											final EditText input = new EditText(context);
											new AlertDialog.Builder(context).setTitle(context.getString(R.string.preset_name)).setView(input).setPositiveButton("Ok", new DialogInterface.OnClickListener() {
												@Override
												public void onClick(DialogInterface dialog, int whichButton) {
													Editable value = input.getText();
													if (!("" + value).trim().equals("")) {
														gp.setName("" + value);
														((PresetTagObject) img.tagObject).text2D.setText(gp.getName());
														GamePresetDao.getInstance(context).persist(gp);
														Image2D delBt = new Image2D(context, "D" + R.drawable.preset_delete);
														delBt.x = img.x;
														delBt.y = img.y;
														delBt.tagObject = img.tagObject;
														presetButtons.remove(img);
														((PresetTagObject) img.tagObject).presetGroup.removeObject(img);
														presetButtons.add(delBt);
														((PresetTagObject) img.tagObject).presetGroup.addObject(delBt);
													}
													disableTouch = false;
												}
											}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
												@Override
												public void onClick(DialogInterface dialog, int whichButton) {
													disableTouch = false;
												}
											}).show();
										}
									});

								}
							});
							disableTouch = true;
							return;
						} else {
							removePreset(img);
							return;
						}
					}
				}

				for (IObject2D o : presetBgs) {
					final Image2D img = (Image2D) o;
					if (img.contains(nx, ny)) {
						if (selectedPreset != img) {
							if (selectedPreset != null) {
								selectedPreset.setUri("D" + R.drawable.preset_item_bg);
							}
							img.setUri("D" + R.drawable.preset_item_sel_bg);
							selectedPreset = img;
							return;
						} else {
							view.removeScreen(1);
							callback.rollPreset(((PresetTagObject) img.tagObject).gamePreset);

							return;
						}
					}
				}
			} else {

			}
			touchMove = false;
		}
	}

	private void selectButton(Image2D img, Runnable run) {
		Scale2DAnimation sc = new Scale2DAnimation(img, 500, 0, 0.3f, 1f);
		sc.setInterpolation(new BounceInterpolator());
		addAnimation(sc);
		postDelayed(run, 500);
	}

	private void removePreset(Image2D button) {
		disableTouch = true;
		final AccelerateInterpolator itp = new AccelerateInterpolator();
		final PresetTagObject tag = (PresetTagObject) button.tagObject;
		presetButtons.remove(button);
		selectButton(button, new Runnable() {

			@Override
			public void run() {
				GamePresetDao.getInstance(context).delete(tag.gamePreset);
				for (IObject2D presetGrp : presetElements.getObjects()) {
					if (presetGrp != tag.presetGroup && presetGrp.getY() > tag.presetGroup.getY()) {
						Translation2DAnimation animV = new Translation2DAnimation(presetGrp, 300, 400, 0, -90);
						animV.setInterpolation(itp);
						addAnimation(animV);
					}
				}

				Translation2DAnimation anim = new Translation2DAnimation(tag.presetGroup, 400, 0, 768, 0);
				anim.setInterpolation(itp);
				anim.setRemoveComponentAtEnd(true);
				addAnimation(anim);

				disableTouch = false;
			}
		});
	}

	private void scrollItemsTo(int y) {
		if (y > 0) {
			y = 0;
		} else {
			int nb = presetElements.getObjects().size() - 7;
			if (nb <= 0) {
				y = 0;
			} else {
				y = Math.max(-nb * 90, y);
			}
		}

		presetElements.setY(y);

	}

	public interface CallBack {

		void rollPreset(GamePreset preset);
	}

}
